package com.lechi.web.server.handle;

import com.alibaba.fastjson2.JSON;
import com.lechi.web.common.utils.bean.BeanUtils;
import com.lechi.web.common.utils.spring.SpringUtils;
import com.lechi.web.constants.Constants;
import com.lechi.web.framework.util.GuavaCacheUtil;
import com.lechi.web.framework.websocket.WebSocketServer;
import com.lechi.web.framework.websocket.WebSocketUtil;
import com.lechi.web.service.IIotMonitorDataService;
import com.lechi.web.system.domain.IotMonitorDataBo;
import com.lechi.web.system.domain.IotWeatherDeviceBo;
import com.lechi.web.system.domain.IotWeatherSensorParseBo;
import com.lechi.web.util.RecordFileUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 二代站报文接收
 */
@Slf4j
@Sharable
public final class Weather2024InboundMessageHandler extends SimpleChannelInboundHandler<ByteBuf> implements BaseWeatherInboundHandle {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) {
        String hostName = getHostName(ctx);
        String dataRecord = byteBuf.toString(Charset.defaultCharset());
        log.error("WEATHER-2024设备地址： {} ，开始解析报文：{}", hostName, dataRecord);
//        if (!dataRecord.startsWith($DATADICK) || !checkEquals(dataRecord.replace("$", ""))) {
        if (!getKeysByValue(hostName).isEmpty()) {
            getKeysByValue(hostName).forEach(deviceId -> WebSocketServer.sendInfo(deviceId + 1000, JSON.toJSONString(Map.of("response", dataRecord))));
        }
        if (dataRecord.startsWith($DATADICK) && !checkEquals(dataRecord.replace("$", ""))) {
            return;
        }
        List<IotWeatherDeviceBo> weatherDeviceBoList = (List<IotWeatherDeviceBo>) GuavaCacheUtil.getCmdParseTableMap().getOrDefault(Constants.WEATHER2024, new ArrayList<>());
        String deviceStation = null;
        int sensorBeginIndex = 0;
        Date watchTime = null;
        String dataType = "";
        boolean deviceSignBool = false;
        boolean stationNumBool = false;
        String[] sensorAndStateData = dataRecord.split(",");
        try {
            for (IotWeatherDeviceBo iotWeatherDeviceBo : weatherDeviceBoList) {
                stationNumBool = Objects.equals(iotWeatherDeviceBo.getDeviceStation(), sensorAndStateData[iotWeatherDeviceBo.getStationNumIndex()]);
                deviceSignBool = Objects.equals(iotWeatherDeviceBo.getDeviceSign(), sensorAndStateData[iotWeatherDeviceBo.getDeviceSignIndex()]);
                dataType = sensorAndStateData[iotWeatherDeviceBo.getDeviceSignIndex() + 2];
                if (deviceSignBool && stationNumBool) {
                    deviceStation = iotWeatherDeviceBo.getDeviceStation();
                    GuavaCacheUtil.getDeviceLastDated().put(iotWeatherDeviceBo.getDeviceId().toString(), new Date());
                    GuavaCacheUtil.getDeviceIdAndIPMap().put(iotWeatherDeviceBo.getDeviceId(), hostName);
                    watchTime = Optional.ofNullable(sensorAndStateData[iotWeatherDeviceBo.getDateTimeIndex()]).map(this::parseStrToDate).orElse(null);
                    sensorBeginIndex = iotWeatherDeviceBo.getWatchDataIndex();
                    break;
                }
            }
        } catch (Exception e) {
            log.error("WEATHER-2024解析报文异常：{}", dataRecord, e);
        }
        if (Objects.equals("ME", dataType) || watchTime == null) {
            return;
        }
        Map<String, IotWeatherSensorParseBo> sensorParseBoMap = GuavaCacheUtil.getWeatherParseTableMap().getOrDefault(deviceStation, new HashMap<>());
        List<IotMonitorDataBo> weather2024DeviceDataList = new ArrayList<>();
        int step = 2;
        for (int i = sensorBeginIndex, length = sensorAndStateData.length; i < length - step; i = i + step) {
            if ("/".equals((sensorAndStateData[i + 1]))) {
                step = 1;
                continue;
            }
            if (sensorParseBoMap.containsKey(sensorAndStateData[i])) {
                IotWeatherSensorParseBo sensorParseBo = sensorParseBoMap.get(sensorAndStateData[i].trim());
                IotMonitorDataBo iotMonitorPageData = new IotMonitorDataBo();
                BeanUtils.copyProperties(sensorParseBo, iotMonitorPageData);
                step = GuavaCacheUtil.getStateCodeMap().containsKey(sensorAndStateData[i + 2]) ? 3 : 2;
                String doubleValue = Optional.ofNullable(sensorAndStateData[i + 1]).orElse("");
                if ("string".equals(sensorParseBo.getValueType())) {
                    iotMonitorPageData.setDoubleValue(doubleValue).setStringValue(doubleValue).setDateTime(watchTime);
                } else {
                    try {
                        var v = Double.parseDouble(doubleValue) * Optional.ofNullable(sensorParseBo.getIntFactor()).orElse(1d);
                        String formatV = new DecimalFormat(Optional.ofNullable(sensorParseBo.getSensorDigit()).filter(n -> n > 0).map(n -> "0." + "0".repeat(n)).orElse("0")).format(v);
                        iotMonitorPageData.setValue(Float.parseFloat(formatV)).setStringValue(formatV).setDoubleValue(formatV).setDateTime(watchTime);
                    } catch (NumberFormatException e) {
                        log.error("WEATHER-2024解析报文NumberFormatException异常：{}", dataRecord);
                        continue;
                    }
                }
                Optional.ofNullable(sensorAndStateData[i + 2]).filter(x -> GuavaCacheUtil.getStateCodeMap().containsKey(x)).ifPresent(iotMonitorPageData::setQualityCode);
//                IotMonitorDataBo iotMonitorDataBo = GuavaCacheUtil.getMonitorDataMap().get(iotMonitorPageData.getDeviceId(), iotMonitorPageData.getSensorAliasId());
                weather2024DeviceDataList.add(iotMonitorPageData);
                iotMonitorPageData.setTableName(Constants.MONITOR_DATA_TABLE + iotMonitorPageData.getDeviceId());
                insertData(iotMonitorPageData);
                alarmRuleChain(iotMonitorPageData);
                WebSocketUtil.sendToMonitorPage(iotMonitorPageData);
                GuavaCacheUtil.getMonitorDataMap().put(iotMonitorPageData.getDeviceId(), iotMonitorPageData.getSensorAliasId(), iotMonitorPageData);
//                if (iotMonitorDataBo == null || (iotMonitorDataBo.getDateTime() != null && watchTime.after(iotMonitorDataBo.getDateTime()))) {
//                    iotMonitorPageData.setTableName(Constants.MONITOR_DATA_TABLE + iotMonitorPageData.getDeviceId());
//                    insertData(iotMonitorPageData);
//                    alarmRuleChain(iotMonitorPageData);
//                    WebSocketUtil.sendToMonitorPage(iotMonitorPageData);
//                    GuavaCacheUtil.getMonitorDataMap().put(iotMonitorPageData.getDeviceId(), iotMonitorPageData.getSensorAliasId(), iotMonitorPageData);
//                } else {
//                    updateData(iotMonitorPageData);
//                }
            }
        }
        WebSocketUtil.sendToDevicePage(Constants.WEATHER2024, weather2024DeviceDataList, dataRecord);
        RecordFileUtil.producerRecord(weather2024DeviceDataList, dataRecord, "");
        RecordFileUtil.producerRecordCsv(weather2024DeviceDataList);
    }

    private void updateData(IotMonitorDataBo iotMonitorDataBo) {
        CompletableFuture.runAsync(() -> {
            iotMonitorDataBo.setTableName(Constants.MONITOR_DATA_TABLE + iotMonitorDataBo.getDeviceId());
            Long id = SpringUtils.getBean(IIotMonitorDataService.class).selectExistsMonitorData(iotMonitorDataBo);
            if (id != null && id.longValue() != 0) {
                iotMonitorDataBo.setId(id);
                SpringUtils.getBean(IIotMonitorDataService.class).updateExistsMonitorData(iotMonitorDataBo);
            } else {
                insertData(iotMonitorDataBo);
            }
        });
    }
}
